
import { _decorator, Component, Node, Mesh, utils, MeshRenderer, color } from 'cc';
import GameConfig from '../../Script/GameSpecial/GameConfig';
import yyComponent from '../../Script/Common/yyComponent';
const { ccclass, property } = _decorator;

/**单一路段模型 */
@ccclass('RoadItem')
export class RoadItem extends yyComponent {

    public static roadItemLen: number = 100;
    public static houdu: number = 1;
    protected static meshData;
    protected static _mesh: Mesh;
    protected static get mesh(): Mesh {
        if (!this._mesh) {
            this.createMesh();
        }
        return this._mesh;
    }
    protected static createMesh() {
        this.meshData = {
            positions: [],
            normals: [],
            indices: [],
            uvs: [],
        };
        this.houdu = GameConfig.GameRule.roadHouDu;
        
        let r = GameConfig.GameRule.roadHalfWidth;//半径
        let radianCount = 21;//圆周上的顶点数量
        let startRadian = Math.PI * 0.5 - GameConfig.GameRule.roadMaxRadian;
        let endRadian = Math.PI * 0.5 - GameConfig.GameRule.roadMinRadian;
        let stepRadian = (endRadian - startRadian) / (radianCount - 1);
        let inPI = 1 / (endRadian - startRadian);
        let startUVx = startRadian * inPI;
        let len = this.roadItemLen;//单个节点的总长度
        let lenCount = 21;//Z轴线上的顶点数量
        let stepZ = len / (lenCount - 1);
        let inLen = 1 / len;
        //内侧表面
        for (let i1 = 0; i1 < radianCount; ++i1) {
            let radian = i1 * stepRadian + startRadian;
            let s1 = Math.sin(radian);
            let c1 = Math.cos(radian);
            let x = r * c1;
            let y = -r * s1;
            let uvx = 1 - radian * inPI + startUVx;
            for (let z1 = 0; z1 < lenCount; ++z1) {
                let posZ = z1 * stepZ;
                this.meshData.positions.push(x, y, -posZ);
                this.meshData.normals.push(-c1, s1, 0);
                this.meshData.uvs.push(uvx, 1 - posZ * inLen);
            }
        }
        for (let rc = 0; rc < radianCount - 1; ++rc) {
            for (let z2 = 0; z2 < lenCount - 1; ++z2) {
                let i2 = rc * lenCount + z2;
                this.meshData.indices.push(i2, i2 + 1, i2 + lenCount, i2 + 1, i2 + lenCount + 1, i2 + lenCount);
            }
        }

        //外侧表面
        let tempX = this.meshData.positions[0] + this.houdu / Math.cos(startRadian);
        let tempY = -this.meshData.positions[1];
        let waiStartRadian = Math.atan2(tempY, tempX);
        tempX = r * Math.cos(endRadian) + this.houdu / Math.cos(endRadian);
        tempY = r * Math.sin(endRadian);
        let waiEndRadian = Math.atan2(tempY, tempX);
        stepRadian = (waiEndRadian - waiStartRadian) / (radianCount - 1);
        r += this.houdu;
        for (let i3 = 0; i3 < radianCount; ++i3) {
            let radian = i3 * stepRadian + waiStartRadian;
            let s2 = Math.sin(radian);
            let c2 = Math.cos(radian);
            let x = r * c2;
            let y = -r * s2;
            let uvx = 1 - radian * inPI + startUVx;
            for (let z3 = 0; z3 < lenCount; ++z3) {
                let posZ = z3 * stepZ;
                this.meshData.positions.push(x, y, -posZ);
                this.meshData.normals.push(c2, -s2, 0);
                this.meshData.uvs.push(uvx, 1 - posZ * inLen);
            }
        }
        let offset = radianCount * lenCount;
        for (let rc = 0; rc < radianCount - 1; ++rc) {
            for (let z4 = 0; z4 < lenCount - 1; ++z4) {
                let i4 = rc * lenCount + z4 + offset;
                this.meshData.indices.push(i4 + 1, i4, i4 + lenCount, i4 + 1, i4 + lenCount, i4 + lenCount + 1);
            }
        }

        //封面
        offset *= 2;
        let x1 = Math.cos(startRadian) * (r - this.houdu);
        let y1 = -Math.sin(startRadian) * (r - this.houdu);
        let x2 = Math.cos(waiStartRadian) * r;
        let y2 = -Math.sin(waiStartRadian) * r;
        let x3 = Math.cos(endRadian) * (r - this.houdu);
        let y3 = -Math.sin(endRadian) * (r - this.houdu);
        let x4 = Math.cos(waiEndRadian) * r;
        let y4 = -Math.sin(waiEndRadian) * r;

        for (let z5 = 0; z5 <= len; z5 += stepZ) {
            this.meshData.positions.push(x1, y1, -z5, x2, y2, -z5, x3, y3, -z5, x4, y4, -z5);
            // this.meshData.normals.push(sin1, cos1, 0, sin1, cos1, 0, sin2, cos2, 0, sin2, cos2, 0);
            this.meshData.normals.push(0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0);
            let uvy = 1 - z5 * inLen;
            this.meshData.uvs.push(1, uvy, 1, uvy, 0, uvy, 0, uvy);
        }
        for (let z6 = 0; z6 < lenCount - 1; ++z6) {
            let i5 = offset + z6 * 4;
            this.meshData.indices.push(i5, i5 + 1, i5 + 5, i5, i5 + 5, i5 + 4, i5 + 2, i5 + 6, i5 + 7, i5 + 2, i5 + 7, i5 + 3);
        }

        this._mesh = new Mesh();
        this._mesh = utils.createMesh(this.meshData);
    }


    protected initSub() {
        this.initMesh();
    }

    @property(MeshRenderer)
    protected meshRender: MeshRenderer = null;
    protected initMesh() {
        this.meshRender.mesh = RoadItem.mesh;
    }

}

